package net.esj.basic.plugins.struts2.resultsupport;

import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.Writer;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import net.esj.basic.plugins.freemarker.SpringConfigToFreemarkerManager;
import net.esj.basic.plugins.freemarker.UsageFreemarkerManager;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.config.DefaultSettings;
import org.apache.struts2.views.freemarker.FreemarkerManager;
import org.apache.struts2.views.freemarker.FreemarkerResult;
import org.apache.struts2.views.util.ResourceUtil;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.inject.Inject;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import freemarker.template.TemplateModel;

/**
 * freemarker模板，先选择webapp下用户定义的ftl文件，如果不存在则在找寻classloarder下的文件
 * @author Administrator
 *
 */
public class FreemarkerUsageResult extends FreemarkerResult {

	private static final String STRUTS_FREEMARKER_USAGE = "struts.freemarker.usage";
	
	private static final String PARENT_TEMPLATE_WRITER = FreemarkerUsageResult.class.getName() +  ".parentWriter";
	
	protected UsageFreemarkerManager usageFreemarkerManager;
	
	private Configuration userConfiguration;
	
	@Inject(value="struts")
	public void setUsageFreemarkerManager(
			UsageFreemarkerManager usageFreemarkerManager) {
		this.usageFreemarkerManager = usageFreemarkerManager;
	}
	
	@Override
	public void doExecute(String locationArg, ActionInvocation invocation)
			throws IOException, TemplateException {
		
		this.location = locationArg;
        this.invocation = invocation;
        this.configuration = getConfiguration();
        this.wrapper = getObjectWrapper();

        ActionContext ctx = invocation.getInvocationContext();
        HttpServletRequest req = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
        if (!locationArg.startsWith("/")) {
            String base = ResourceUtil.getResourceBase(req);
            locationArg = base + "/" + locationArg;
        }

        Template template = null;
		try{
			//if(canUserConfiguration(invocation)){
				userConfiguration = getUserConfiguration();
				template = userConfiguration.getTemplate(locationArg,
						deduceLocale());
			//}
		}catch(Exception e){
			//NOUSE
		}finally{
			if(template==null){
				template = configuration.getTemplate(locationArg,
						deduceLocale());
			}
		}
        //Template template = configuration.getTemplate(locationArg, deduceLocale());
        TemplateModel model = createModel();

        // Give subclasses a chance to hook into preprocessing
        if (preTemplateProcess(template, model)) {
            try {
                // Process the template
                Writer writer = getWriter();
                if (isWriteIfCompleted() || configuration.getTemplateExceptionHandler() == TemplateExceptionHandler.RETHROW_HANDLER) {
                    CharArrayWriter parentCharArrayWriter = (CharArrayWriter) req.getAttribute(PARENT_TEMPLATE_WRITER);
                    boolean isTopTemplate = false;
                    if (isTopTemplate = (parentCharArrayWriter == null)) {
                        //this is the top template
                        parentCharArrayWriter = new CharArrayWriter();
                        //set it in the request because when the "action" tag is used a new VS and ActionContext is created
                        req.setAttribute(PARENT_TEMPLATE_WRITER, parentCharArrayWriter);
                    }

                    try {
                        template.process(model, parentCharArrayWriter);

                        if (isTopTemplate) {
                            parentCharArrayWriter.flush();
                            parentCharArrayWriter.writeTo(writer);
                        }
                    } finally {
                        if (isTopTemplate && parentCharArrayWriter != null) {
                            req.removeAttribute(PARENT_TEMPLATE_WRITER);
                            parentCharArrayWriter.close();
                        }
                    }
                } else {
                    template.process(model, writer);
                }
            } finally {
                // Give subclasses a chance to hook into postprocessing
                postTemplateProcess(template, model);
            }
        }
	}
	
	protected Configuration getUserConfiguration() {
		return usageFreemarkerManager.getUserConfiguration(ServletActionContext
				.getServletContext());
	}

	protected boolean canUserConfiguration(ActionInvocation invocation){
		String packetName = invocation.getAction().getClass().getPackage().getName();
		String actionname = invocation.getAction().getClass().getName();
		String[] strs = DefaultSettings.get(STRUTS_FREEMARKER_USAGE).split(";");
		for(String str : strs){
			if(packetName.startsWith(str)
					|| str.equals(actionname)){
				return true;
			}
		}
		return false;
	}
}
